﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Repo7.BusinessLogic.Utils;
using System.Net;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace Repo7.BusinessLogic.Network.Commander
{
    /// <summary>
    /// Repo Command 
    /// </summary>
    [Serializable]
    public class RepoCommand
    {
        #region Public Properties

        /// <summary>
        /// End Point that must receive the command
        /// </summary>
        public IPEndPoint CommandReceiver { get; set; }

        /// <summary>
        /// Command Type
        /// </summary>
        public CommandTypes CommandType { get; set; }

        /// <summary>
        /// IP End Point to send to.
        /// </summary>
        public IPEndPoint SendToEndPoint { get; set; }

        /// <summary>
        /// IP End Point to receive from.
        /// </summary>
        public IPEndPoint ReceiveEndPoint { get; set; }

        /// <summary>
        /// File Name
        /// </summary>
        public string FileName { get; set; }

        #endregion

        #region Public Mehtods

        /// <summary>
        /// Get bytes 
        /// </summary>
        /// <returns></returns>
        public byte[] GetBytes()
        {
            using (MemoryStream memStream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(memStream, this);
                byte[] messageSize = BitConverter.GetBytes((long)memStream.Length);
                byte[] ret = new byte[messageSize.Length + memStream.Length];

                messageSize.CopyTo(ret, 0);
                memStream.ToArray().CopyTo(ret, messageSize.Length);
                return ret;
            }
        }

        #endregion

        #region Static Methods

        /// <summary>
        /// Get RepoMessage From Stream
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static RepoCommand GetRepoNetMessage(Stream stream)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            stream.Seek(0, SeekOrigin.Begin);
            return formatter.Deserialize(stream) as RepoCommand;
        }

        /// <summary>
        /// Create a SEND Command
        /// </summary>
        /// <param name="filePath">File to be Sent</param>
        /// <param name="endPoint">Send to End Point</param>
        /// <returns></returns>
        public static RepoCommand CreateSendCommand(IPEndPoint commandReceiver, string filePath, IPEndPoint endPoint)
        {
            RepoCommand command = new RepoCommand();
            command.CommandReceiver = commandReceiver;
            command.CommandType = CommandTypes.SEND_FILE_TRANSFER;
            command.SendToEndPoint = endPoint;

            return command;
        }

        /// <summary>
        /// Create a RECEIVE Command
        /// </summary>
        /// <param name="filePath">File to be Sent</param>
        /// <param name="endPoint">Send to End Point</param>
        /// <returns></returns>
        public static RepoCommand CreateReceiveCommand(IPEndPoint commandReceiver, string filePath, IPEndPoint endPoint)
        {
            RepoCommand command = new RepoCommand();
            command.CommandReceiver = commandReceiver;
            command.CommandType = CommandTypes.RECEIVE_FILE_TRANSFER;
            command.ReceiveEndPoint = endPoint;

            return command;
        }

        /// <summary>
        /// Create a TUNNEL Command
        /// </summary>
        /// <param name="filePath">File to be Sent</param>
        /// <param name="endPoint">Send to End Point</param>
        /// <returns></returns>
        public static RepoCommand CreateReceiveCommand(IPEndPoint commandReceiver, string filePath, IPEndPoint receiveEndPoint, IPEndPoint sendEndPoint)
        {
            RepoCommand command = new RepoCommand();
            command.CommandReceiver = commandReceiver;
            command.CommandType = CommandTypes.TUNNEL_FILE_TRANSFER;
            command.ReceiveEndPoint = receiveEndPoint;
            command.SendToEndPoint = sendEndPoint;

            return command;
        }

        #endregion
    }
}
